home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / gfx / fract / FlashMandel.lha / FlashMandel / Sources / Modules / Iff.c < prev    next >
C/C++ Source or Header  |  1999-01-22  |  54KB  |  1,890 lines

  1. /******************************************************************************
  2. **
  3. **  Coded by Dino Papararo 11-May-1998
  4. **
  5. **  Based on NewIff package relased by Commodore
  6. **
  7. **  FUNCTION
  8. **
  9. **    QueryMandPic -- Examine an IFF picture.
  10. **
  11. **  SYNOPSIS
  12. **
  13. **    LONG QueryMandPic (struct ILBMInfo *,struct MandelChunk **,UBYTE *);
  14. **
  15. **  DESCRIPTION
  16. **
  17. **    Passed an initialized ILBMInfo with a not-in-use IFFHandle, a MandelChunk
  18. **
  19. **    structure and a filename, will open an ILBM, fill in ilbm->camg and
  20. **
  21. **    ilbm->bmhd, and close the ILBM.
  22. **
  23. **    This allows you to determine if the ILBM is a size and
  24. **
  25. **    type you want to deal with.
  26. **
  27. **    For succes is necessary the ID_MAND into the iff file !
  28. **
  29. **    Returns 0 for success or an IFFERR (libraries/iffparse.h).
  30. **
  31. **
  32. **  FUNCTION
  33. **
  34. **    LoadMandPic -- Load an IFF picture.
  35. **
  36. **  SYNOPSIS
  37. **
  38. **    LONG LoadMandPic (struct ILBMInfo *,UBYTE *);
  39. **
  40. **  DESCRIPTION
  41. **
  42. **    Function uses a ILBMInfo struct with record ParseInfo.iff initialized
  43. **
  44. **    with AllocIFF() function, and a pointer to a FileName.
  45. **
  46. **    It's necessary a valid Window RPort and ViewPort initialized in the passed
  47. **
  48. **    ILBM Structure for the BODY and COLORS, at end all memory will be freed.
  49. **
  50. **
  51. **  FUNCTION
  52. **
  53. **    SaveMandPic -- save a screen as IFF picture.
  54. **
  55. **  SYNOPSIS
  56. **
  57. **    LONG SaveMandPic (struct ILBMInfo *,struct Chunk *,struct Chunk *,UBYTE *);
  58. **
  59. **  DESCRIPTION
  60. **
  61. **    Function uses a ILBMInfo struct with record ParseInfo.iff initialized
  62. **
  63. **    with AllocIFF() function, two custom chunks, and a pointer to a FileName.
  64. **
  65. **    In the 1st custom chunk I put the copyright infos and in the 2nd the
  66. **
  67. **    special chunk MAND used for window limits, fractal limits, iterations
  68. **
  69. **    type...
  70. **
  71. **    Function will save the icon file too with support for NewIcons.
  72. **
  73. ******************************************************************************/
  74.  
  75. #define INTUI_V36_NAMES_ONLY
  76. #define __USE_SYSBASE
  77.  
  78.  
  79. #include <proto/intuition.h>
  80. #include <proto/graphics.h>
  81. #include <proto/icon.h>
  82. #include <proto/iffparse.h>
  83. #include <proto/wb.h>
  84.  
  85. #include <exec/types.h>
  86. #include <intuition/intuitionbase.h>
  87. #include <intuition/screens.h>
  88. #include <graphics/gfxbase.h>
  89. #include <workbench/workbench.h>
  90.  
  91. #include <iffp/ilbm.h>
  92. #include <iffp/ilbmapp.h>
  93. #include <iffp/iff.h>
  94. #include <iffp/packer.h>
  95. #include <iffp/iffpstrings.h>
  96.  
  97. UBYTE *omodes [2] = {"r","w"};
  98.  
  99. static BYTE *PutDump(BYTE *,int);
  100.  
  101. static BYTE *PutRun(BYTE *,int,int);
  102.  
  103. #define MaxSrcPlanes (25)
  104.  
  105. #define ID_MAND MAKE_ID('M','A','N','D')
  106.  
  107. #define NOMAND 4L
  108.  
  109. #define TOBLACK   1
  110. #define FROMBLACK 0
  111.  
  112. #define DUMP    0
  113. #define RUN    1
  114. #define MinRun 3
  115. #define MaxRun 128
  116. #define MaxDat 128
  117. #define INBUFSZ 128
  118. #define BODYBUFSZ    5004
  119. #define GetByte()       (*source++)
  120. #define PutByte(c)      { *dest++ = (c);   ++PackPutSize; }
  121. #define OutDump(nn)     dest = PutDump(dest, nn)
  122. #define OutRun(nn,cc)   dest = PutRun(dest, nn, cc)
  123. #define UGetByte()    (*source++)
  124. #define UPutByte(c)    (*dest++ = (c))
  125.  
  126. IMPORT BOOL Fade (struct Window *,ULONG *,ULONG,ULONG,BOOL);
  127.  
  128. /* local function prototypes */
  129.  
  130. struct  CatCompArrayType CatCompArray [8];
  131.  
  132. LONG QueryMandPic (struct ILBMInfo *,struct MandelChunk **,UBYTE *filename);
  133.  
  134. LONG LoadMandPic (struct ILBMInfo *,UBYTE *);
  135.  
  136. LONG SaveMandPic (struct ILBMInfo *,struct Chunk *,struct Chunk *,UBYTE *);
  137.  
  138. LONG SavePalette (struct ILBMInfo *,struct Chunk *,UBYTE *);
  139.  
  140. LONG LoadPalette (struct ILBMInfo *,UBYTE *);
  141.  
  142. static LONG __saveds __asm stdio_stream (register __a0 struct Hook *,register __a2 struct IFFHandle *,register __a1 struct IFFStreamCmd *);
  143.  
  144. LONG saveilbm (struct ILBMInfo *,struct BitMap *,ULONG,WORD,WORD,WORD,WORD,APTR,UWORD,UWORD,WORD,WORD,struct Chunk *,struct Chunk *,UBYTE *);
  145.  
  146. LONG initbmhd (BitMapHeader *,struct BitMap *,WORD,WORD,WORD,WORD,WORD,WORD,WORD,ULONG);
  147.  
  148. LONG loadcmap (struct ILBMInfo *);
  149.  
  150. LONG putcmap (struct IFFHandle *,APTR,UWORD,UWORD);
  151.  
  152. LONG loadbody (struct IFFHandle *,struct BitMap *,BitMapHeader *);
  153.  
  154. LONG loadbody2 (struct IFFHandle *,struct BitMap *,BYTE *,BitMapHeader *,BYTE *,ULONG);
  155.  
  156. LONG putbody (struct IFFHandle *,struct BitMap *,BYTE *,BitMapHeader *,BYTE *,LONG);
  157.  
  158. ULONG getcamg (struct ILBMInfo *);
  159.  
  160. LONG openifile (struct ParseInfo *,UBYTE *,ULONG);
  161.  
  162. LONG parseifile (struct    ParseInfo *,LONG,LONG,LONG *,LONG *,LONG *);
  163.  
  164. VOID closeifile (struct ParseInfo *);
  165.  
  166. VOID initiffasstdio (struct IFFHandle *);
  167.  
  168. LONG PutCk (struct IFFHandle *,LONG,LONG,VOID *);
  169.  
  170. LONG getcolors (struct ILBMInfo *);
  171.  
  172. LONG alloccolortable (struct ILBMInfo *);
  173.  
  174. LONG setcolors (struct ILBMInfo *,struct ViewPort *);
  175.  
  176. VOID freecolors (struct ILBMInfo *);
  177.  
  178. LONG chkcnt (LONG *);
  179.  
  180. LONG getcontext (struct IFFHandle *);
  181.  
  182. LONG contextis (struct IFFHandle *,LONG,LONG);
  183.  
  184. LONG currentchunkis (struct IFFHandle *,LONG,LONG);
  185.  
  186. UBYTE *findpropdata (struct IFFHandle *,LONG,LONG);
  187.  
  188. static BYTE *PutDump (BYTE *,int);
  189.  
  190. static BYTE *PutRun (BYTE *,int,int);
  191.  
  192. LONG PackRow (BYTE **,BYTE **,LONG);
  193.  
  194. BOOL UnPackRow (BYTE **,BYTE **,WORD,WORD);
  195.  
  196. LONG PackPutSize;
  197.  
  198. char PackBuffer [256];    /* [TBD] should be 128?  on stack?*/
  199.  
  200. /* Data for project icon for saved ILBM */
  201.  
  202. UWORD ILBMI1Data [] =
  203. {
  204.   /* Plane 0*/
  205.   0x0000,0x0000,0x0000,0x0001,0x7fff,0xffff,0xffff,0xffff,  0x1fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,
  206.   0x7fff,0xffff,0xffff,0xffff,0x3fff,0xffff,0xffff,0xffff,  0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffdf,0xffff,
  207.   0x7fff,0xffff,0xffff,0x7fff,0x7fff,0xffff,0xffff,0x7fff,  0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,
  208.   0x7fff,0xffff,0xfdff,0xbfff,0x7fff,0xffff,0xfdff,0xffff,  0x7fff,0xffff,0xf7ff,0xfbff,0x7fff,0xffff,0xffff,0xffff,
  209.   0x7fff,0xffff,0xffff,0xffbf,0x7fff,0xfffe,0x7fff,0xffff,  0x7fff,0xfffe,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,
  210.   0x7fff,0xfffd,0xffff,0xffef,0x7fff,0xffff,0xffff,0xffcf,  0x7fff,0xffff,0xffff,0xffdf,0x7fff,0xee3f,0xffff,0xffff,
  211.   0x7fff,0xffdf,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,  0x7fff,0xfff7,0xffff,0xffff,0x7fff,0x7ff3,0xffff,0xffff,
  212.   0x7ffb,0xffff,0xffff,0xffff,0x7ffe,0xffff,0xffff,0xffff,  0x6b7f,0xffff,0xffff,0xffff,0x7ffb,0xffff,0xffff,0xffff,
  213.   0x7fff,0xfff3,0xffff,0xffff,0x7fff,0xfff7,0xffff,0xffff,  0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffef,0xffff,0xffff,
  214.   0x7fff,0xffdf,0xffff,0xffff,0x7fff,0xdfff,0xffff,0xffdf,  0x7fff,0xfdff,0xffff,0xffdf,0x7fff,0xffff,0xffff,0xffff,
  215.   0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,  0x7fff,0xfffe,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,
  216.   0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffff,0xfdff,  0x7fff,0xffff,0xf7ff,0xfbbf,0x7fff,0xffff,0xcfff,0xffff,
  217.   0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffee,0xffff,  0x7fff,0xffff,0xffff,0x7fff,0x7fff,0xffff,0xffff,0x7fff,
  218.   0x7fff,0xffff,0xffff,0x7fff,0x7fff,0xffff,0xffcf,0xffff,  0x7fff,0xffff,0xfffd,0xffff,0x3fff,0xffff,0xffff,0xffff,
  219.   0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,  0x5fff,0xffff,0xffff,0xffff,0x1fff,0xffff,0xffff,0xffff,
  220.   0x4fff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  221.   /* Plane 1*/
  222.   0xffff,0xffff,0xffff,0xfffe,0xcfff,0xffff,0xffff,0xfffe,  0xffff,0xffff,0xffff,0x7ffe,0xbfff,0xffff,0xffff,0xfffe,
  223.   0xffff,0xffff,0xffff,0xfffe,0xffff,0xffff,0xffff,0xfffe,  0xbfff,0xffff,0xfffb,0xfffe,0xffff,0xffff,0xffc1,0xfffe,
  224.   0xffff,0xffff,0xffe0,0x7ffe,0xffff,0xffff,0xffe0,0x7ffe,  0xffff,0xffff,0xffe1,0xfffe,0xffff,0xffff,0xfff3,0xfffe,
  225.   0xffff,0xffff,0xfdc0,0x3ffe,0xffff,0xffff,0xdc00,0x07fe,  0xffff,0xffff,0xc400,0x03fe,0xffff,0xffff,0xe000,0x003e,
  226.   0xffff,0xffff,0xc000,0x003e,0xffff,0xfffe,0x4000,0x007e,  0xffff,0xfffe,0x0000,0x007e,0xffff,0xffff,0x0000,0x003e,
  227.   0xffff,0xfffc,0x0000,0x000e,0xffff,0xfffe,0x0000,0x000e,  0xffff,0xddfc,0x0000,0x001e,0xffff,0xc83c,0x0000,0x001e,
  228.   0xffff,0xc01c,0x0000,0x001e,0xffff,0xc01c,0x0000,0x003e,  0xffff,0x8004,0x0000,0x003e,0xffff,0x0000,0x0000,0x003e,
  229.   0xfffb,0x0004,0x0000,0x003e,0xfff8,0x0000,0x0000,0x007e,  0xa360,0x0000,0x0000,0x01fe,0xfff9,0x0000,0x0000,0x003e,
  230.   0xffff,0x0000,0x0000,0x003e,0xffff,0x8004,0x0000,0x003e,  0xffff,0x800c,0x0000,0x001e,0xffff,0xc00c,0x0000,0x001e,
  231.   0xffff,0xc01c,0x0000,0x001e,0xffff,0xddfc,0x0000,0x001e,  0xffff,0xfdfe,0x0000,0x001e,0xffff,0xfffe,0x0000,0x001e,
  232.   0xffff,0xffff,0x0000,0x003e,0xffff,0xffff,0x0000,0x003e,  0xffff,0xfffe,0x0000,0x007e,0xffff,0xffff,0xc000,0x00fe,
  233.   0xffff,0xffff,0xe000,0x003e,0xffff,0xffff,0xc000,0x003e,  0xffff,0xffff,0xc400,0x023e,0xffff,0xffff,0xcc00,0x07fe,
  234.   0xffff,0xffff,0xfff1,0xfffe,0xffff,0xffff,0xffe0,0xfffe,  0xffff,0xffff,0xffe0,0x7ffe,0xffff,0xffff,0xffe0,0x7ffe,
  235.   0xffff,0xffff,0xffe0,0x7ffe,0xffff,0xffff,0xffc1,0xfffe,  0xffff,0xffff,0xfff9,0xfffe,0xffff,0xffff,0xffff,0xfffe,
  236.   0xbfff,0xffff,0xffff,0xfffe,0xffff,0xffff,0xffff,0xfffe,  0xffff,0xffff,0xffff,0xfffe,0xffff,0xffff,0xffd7,0xfffe,
  237.   0xffff,0xffff,0xffff,0xfffe,0x0000,0x0000,0x0000,0x0000
  238. };
  239.  
  240. UWORD ILBMI2Data [] =
  241. {
  242.   /* Plane 0*/
  243.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xfffe,  0x9ddd,0xdddd,0xdddd,0xdddc,0xffff,0xffff,0xffff,0xfffe,
  244.   0xf777,0x7777,0x7777,0x7776,0xbfff,0xffff,0xffff,0xfffe,  0xdddd,0xdddd,0xdddd,0xdddc,0xffff,0xffff,0xffc3,0xfffe,
  245.   0xf777,0x7777,0x7775,0x7776,0xffff,0xffff,0xffe8,0x7ffe,  0xdddd,0xdddd,0xddd5,0xdddc,0xffff,0xffff,0xfff3,0xfffe,
  246.   0xf777,0x7777,0x7555,0x3776,0xffff,0xffff,0xdc88,0x8ffe,  0xdddd,0xdddd,0xd555,0x51dc,0xffff,0xffff,0xe222,0x223e,
  247.   0xf777,0x7777,0x5555,0x5536,0xffff,0xfffe,0x4888,0x88fe,  0xdddd,0xdddc,0x5555,0x555c,0xffff,0xffff,0x2222,0x223e,
  248.   0xf777,0x7775,0x5555,0x5546,0xffff,0xfffe,0x8888,0x888e,  0xdddd,0xdddd,0x5555,0x555c,0xffff,0xea3e,0x2222,0x223e,
  249.   0xf777,0x5555,0x5555,0x5556,0xffff,0xc89c,0x8888,0x88be,  0xdddd,0xd555,0x5555,0x555c,0xffff,0x2222,0x2222,0x223e,
  250.   0xf773,0x5555,0x5555,0x5576,0xfff8,0x8888,0x8888,0x88fe,  0xc955,0x5555,0x5555,0x55dc,0xfffb,0x2222,0x2222,0x223e,
  251.   0xf777,0x5551,0x5555,0x5576,0xffff,0x8884,0x8888,0x88be,  0xdddd,0xd55d,0x5555,0x555c,0xffff,0xe22e,0x2222,0x223e,
  252.   0xf777,0x5555,0x5555,0x5556,0xffff,0xddfc,0x8888,0x889e,  0xdddd,0xdddd,0x5555,0x555c,0xffff,0xfffe,0x2222,0x223e,
  253.   0xf777,0x7777,0x5555,0x5576,0xffff,0xffff,0x8888,0x88be,  0xdddd,0xdddc,0x5555,0x555c,0xffff,0xffff,0xe222,0x22fe,
  254.   0xf777,0x7777,0x7555,0x5576,0xffff,0xffff,0xc888,0x88be,  0xdddd,0xdddd,0xd555,0x511c,0xffff,0xffff,0xce22,0x27fe,
  255.   0xf777,0x7777,0x7775,0x7776,0xffff,0xffff,0xffe8,0xfffe,  0xdddd,0xdddd,0xddd5,0x5ddc,0xffff,0xffff,0xffe2,0x7ffe,
  256.   0xf777,0x7777,0x7775,0x7776,0xffff,0xffff,0xffc9,0xfffe,  0xdddd,0xdddd,0xdddd,0xdddc,0xbfff,0xffff,0xffff,0xfffe,
  257.   0xf777,0x7777,0x7777,0x7776,0xffff,0xffff,0xffff,0xfffe,  0xdddd,0xdddd,0xdddd,0xdddc,0x9fff,0xffff,0xffff,0xfffe,
  258.   0xc777,0x7777,0x7777,0x7776,0x0000,0x0000,0x0000,0x0000,
  259.   /* Plane 1*/
  260.   0x0000,0x0000,0x0000,0x0000,0x4fff,0xffff,0xffff,0xffff,  0x7fff,0xffff,0xffff,0x7fff,0x3fff,0xffff,0xffff,0xffff,
  261.   0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,  0x3fff,0xffff,0xfffb,0xffff,0x7fff,0xffff,0xffdd,0xffff,
  262.   0x7fff,0xffff,0xffea,0x7fff,0x7fff,0xffff,0xfff7,0x7fff,  0x7fff,0xffff,0xffeb,0xffff,0x7fff,0xffff,0xffff,0xffff,
  263.   0x7fff,0xffff,0xfdea,0xbfff,0x7fff,0xffff,0xfd77,0x77ff,  0x7fff,0xffff,0xe6aa,0xabff,0x7fff,0xffff,0xfddd,0xddff,
  264.   0x7fff,0xffff,0xeaaa,0xaabf,0x7fff,0xfffe,0x7777,0x777f,  0x7fff,0xfffe,0xaaaa,0xaaff,0x7fff,0xffff,0xdddd,0xddff,
  265.   0x7fff,0xfffc,0xaaaa,0xaaaf,0x7fff,0xffff,0x7777,0x774f,  0x7fff,0xfffe,0xaaaa,0xaa9f,0x7fff,0xcc3d,0xdddd,0xdddf,
  266.   0x7fff,0xea9e,0xaaaa,0xaabf,0x7fff,0xf77f,0x7777,0x777f,  0x7fff,0xaaa6,0xaaaa,0xaabf,0x7fff,0x5dd1,0xdddd,0xddff,
  267.   0x7ffb,0xaaae,0xaaaa,0xaabf,0x7ffe,0x7777,0x7777,0x777f,  0x236a,0xaaaa,0xaaaa,0xabff,0x7ff9,0xdddd,0xdddd,0xddff,
  268.   0x7fff,0xaaa2,0xaaaa,0xaabf,0x7fff,0xf777,0x7777,0x777f,  0x7fff,0xaaae,0xaaaa,0xaabf,0x7fff,0xddcd,0xdddd,0xdddf,
  269.   0x7fff,0xea9e,0xaaaa,0xaabf,0x7fff,0xdfff,0x7777,0x775f,  0x7fff,0xfdfe,0xaaaa,0xaa9f,0x7fff,0xffff,0xdddd,0xdddf,
  270.   0x7fff,0xffff,0xaaaa,0xaabf,0x7fff,0xffff,0x7777,0x777f,  0x7fff,0xfffe,0xaaaa,0xaaff,0x7fff,0xffff,0xdddd,0xddff,
  271.   0x7fff,0xffff,0xeaaa,0xaabf,0x7fff,0xffff,0xf777,0x757f,  0x7fff,0xffff,0xe6aa,0xaabf,0x7fff,0xffff,0xcddd,0xdfff,
  272.   0x7fff,0xffff,0xfffb,0xffff,0x7fff,0xffff,0xffe6,0xffff,  0x7fff,0xffff,0xffea,0x7fff,0x7fff,0xffff,0xfffd,0x7fff,
  273.   0x7fff,0xffff,0xffea,0x7fff,0x7fff,0xffff,0xffc7,0xffff,  0x7fff,0xffff,0xfff9,0xffff,0x7fff,0xffff,0xffff,0xffff,
  274.   0x3fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffff,0xffff,  0x7fff,0xffff,0xffff,0xffff,0x7fff,0xffff,0xffd7,0xffff,
  275.   0x7fff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff
  276. };
  277.  
  278. struct Image ILBMI1 =
  279. {
  280.     0,0,           /* Upper left corner */
  281.     64,62,2,       /* Width, Height, Depth */
  282.     ILBMI1Data,    /* Image data */
  283.     0x0004,0x0000, /* PlanePick, PlaneOnOff */
  284.     NULL           /* Next image */
  285. };
  286.  
  287. struct Image ILBMI2 =
  288. {
  289.     0,0,           /* Upper left corner */
  290.     64,62,2,       /* Width, Height, Depth */
  291.     ILBMI2Data,    /* Image data */
  292.     0x0004,0x0000, /* PlanePick, PlaneOnOff */
  293.     NULL           /* Next image */
  294. };
  295.  
  296. UBYTE *ILBMTools [] =
  297. {
  298.   "FILETYPE=ILBM",
  299.   
  300.   /* NewIcons tooltypes for NewIcons icon */
  301.   
  302.   "*** DON'T EDIT THE FOLLOWING LINES!! ***",
  303.   "IM1=BEI!*£»5#<@¸®®¢;¤9n1(dFJ«¡!m9Ó&TBÇÑ",
  304.   "IM1=ÛdBá(g[®(ß(ÈdB.ÅÞ(Éc9m(ZÝ(ÉS$B6T=Û1(ÉPeJ¦(«.`Ù1¿ÉP¦DB2¥M'@×\"1Â(P¥dS9hj6c¡Ö\"=Á·P¥fW[­·E+A¹Õ\">0²(¥fÈ[®¿Ä2e¡ÅÔ\">,²J¥fÈ[®¿ÈYiB¹",
  305.   "IM1=ZÓ\">,1I(fÈ[®¿È[­µ¢T=Ò\">,5I,·È[®¿È[®·E+A¹Ñ\">,51-¿È[®¿È[®¿RH«.`\">,51m¿È[®¿È[®¿Ä2e¡Å\">,51®¿È[®¿È[®¿Ä2e¡ÅÑ!/&*h·È[®¿È[®¿ÈYiB¹ZÒg",
  306.   "IM1=c%DC[®¿È[®¿È[lj6c¡ÒC²b¦1l¿È[®¿È[­µ¢T=Ó1Á²*hdW[®¿È[®·E+A¹Ó(ÉS%J£;®¿È[®·E+A¹Ô$\\Ab1I-¿È[®·E+A¹Õ\"=Á·P¥fW[­·E+A¹Ö!(Éd8JB9lµE+A¹Ø$",
  307.   "IM1=[¯,5I(d¦+A¹ÁØ\"1/&(¦J¢+A¹1[`Ø.gc8B1SA¹1(e±Ö!¿1C³,·TA¹1(dNÖ=³1(¢À(d=¹1(e¿Õ#­B1(dHg[®(1(®±Õ[dB1(dB1B1\"1+­Õ'XdB1(dB1(dB1[`Õ'(dB",
  308.   "IM1=(dB1(dB1+­×<B1(dB1(dB1[`Ø.Â(dB1(dB7XÛ[dB1(dBÈÝ!¿1(dNÁß'Xe¿â=±ñ",
  309.   "IM2=BEI!-£»5#<@¸®®¢;¤9n1(d9l·VS9ll¦U@#:RS9l±Ò!m(®`Ö",
  310.   "IM2=ÛdBÞ*¦J¦J¦I(Û!J¦JÈ(eJ¦DÚ)D®¿Â!(dUE£Ù5D¦¿È((dB:£»`×5D®³1!+®¿È5IU@Ö5D¦¿1((®¿ÈY*¥«¡Õ)D®³\"1+­dB1,ÆJM0Ô!D¦¿,1(®µB1(¸J¦6hÓ!D®³,·[",
  311.   "IM2=[hfS9n¦J¦J¥`Ò!J®³,·[­dS9lÆJ¦IUJ@Òj­@L·S(fZ¦J¦J¦J¥«®0Ñ*®³\"·S8dS¦J¦J¦J¦J¦ºÒ¥@BÇS9fZ¦J¦J¦J¦JMNhÑEB\"7S9lS¦J¦J¦J¦J¦JÅ`EHBÈ39l»¦J",
  312.   "IM2=¦J¦J¦J¦E¦0Ñ$¡e¿FS9¦J¦J¦J¦J¦J¦NhÑ%B\"7S9l´¦J¦J¦J¦J¦JÅ`ÑJ¡1[ªlS=J¦J¦J¦J¦J7DÒ5X`enB1,ÆJ¦J¦J¦J¢Z@Ñ!Jd$NÃ1(¸J¦J¦J¦J¢Z@Ó¦¿01[®µC9l",
  313.   "IM2=9»¦JMNhÓ!J­@BÈ[hfS9n¦:MNhÕ¥¿Â!(e¿B1(g:¦JhÕ\"JW((dNÃ1(dZ¦Fi@Õ!5K­B01[®¿Ë¤2¤A¦Ö*¦B1!+®À:¦1iI(f`ÖJ¦[d$UJ¦Jhµ¥dTÖJb:¦J¦JMF¦DRJ¥Õ%",
  314.   "IM2=¦$B1(e)J¥»UJC:`Ô*¡dB1(dB4B0U:¦9m@Ò!J(dB1(dB1(dB:¦Jl·¡Ñ!A(dB1(dB1(dCJ%2¦FSHÑ*(dB1(dB1(dU@Ñ2iJ¤9lÑ%HB1(dB1(f¥Ó)D¦Ia@Ò5A(dB1(»",
  315.   "IM2=¡Ô!4j¦J`Ó5A(dCJ×jEJhÕ¦$U@ØE2hÖ\"¥Ú2iDâ)D¡Ó",
  316.   NULL
  317. };
  318.  
  319. struct DiskObject ILBMobject =
  320. {
  321.   WB_DISKMAGIC,                      /* Magic Number */
  322.   WB_DISKVERSION,                    /* Version */
  323.   {                                  /* Embedded Gadget Structure */
  324.     NULL,                            /* Next Gadget Pointer */
  325.     0, 0, 64, 62,                    /* Left,Top,Width,Height */
  326.     GFLG_GADGIMAGE | GADGBACKFILL,   /* Flags */
  327.     GACT_RELVERIFY | GACT_IMMEDIATE, /* Activation Flags */
  328.     GTYP_BOOLGADGET,                 /* Gadget Type */
  329.     (APTR)&ILBMI1,                   /* Render Image */
  330.     (APTR)&ILBMI2,                   /* Select Image */
  331.     NULL,                            /* Text for Gadget*/
  332.     NULL,                            /* Mutual Exclude */
  333.     NULL,                            /* Special Info */
  334.     0,                               /* Gadget ID */
  335.     NULL                             /* User Data */
  336.   },
  337.   WBPROJECT,                        /* Icon Type */
  338.   "MultiView",                      /* Default Tool */
  339.   ILBMTools,                        /* Tool Type Array */
  340.   NO_ICON_POSITION,                 /* Current X */
  341.   NO_ICON_POSITION,                 /* Current Y */
  342.   NULL,                             /* Drawer Structure */
  343.   NULL,                             /* Tool Window */
  344.   NULL                              /* Stack Size */
  345. };
  346.  
  347. struct MandelChunk { WORD LeftEdge,TopEdge,Width,Height;
  348.                      long double RMin,RMax,IMin,IMax;
  349.                      long double RConst,IConst;
  350.                      ULONG Iterations;
  351.                      ULONG Special;
  352.                    };
  353.  
  354. /* saveilbm
  355.  *
  356.  * Given an ILBMInfo with a currently available (not-in-use)
  357.  *   ParseInfo->iff IFFHandle, a BitMap ptr, modeid, widths/heights,
  358.  *   colortable, ncolors, bitspergun, masking, transparent color,
  359.  *   optional chunklists, and filename, will save the bitmap as an ILBM.
  360.  *
  361.  *  if bitspergun=4,  colortable is words, each with nibbles 0RGB
  362.  *  if bitspergun=8,  colortable is byte guns of RGBRGB etc. (like a CMAP)
  363.  *  if bitspergun=32, colortable is ULONG guns of RGBRGB etc.
  364.  *     Only the high eight bits of each gun will be written to CMAP.
  365.  *     Four bit guns n will be saved as nn
  366.  *
  367.  * The struct Chunk *chunklist is for chunks you wish written
  368.  * other than BMHD, CMAP, and CAMG (they will be screened out)
  369.  * because they are calculated and written separately
  370.  *
  371.  * Returns 0 for success, or an IFFERR
  372.  */
  373.  
  374. LONG saveilbm (struct ILBMInfo *ilbm,struct BitMap *bitmap,
  375.                ULONG modeid,WORD width,WORD height,WORD pagewidth,WORD pageheight,
  376.                APTR colortable,UWORD ncolors,UWORD bitspergun,
  377.                WORD masking,WORD transparentColor,
  378.                struct Chunk *chunklist1,struct Chunk *chunklist2,
  379.                UBYTE *filename)
  380. {
  381. struct IFFHandle *iff;
  382.  
  383. struct Chunk *chunk;
  384.  
  385. ULONG chunkID;
  386.  
  387. UBYTE *bodybuf;
  388.  
  389. LONG size, error;
  390.  
  391.   iff = ilbm->ParseInfo.iff;
  392.  
  393.   if (! (modeid & 0xFFFF0000)) modeid &= OLDCAMGMASK;
  394.  
  395.   if (! (bodybuf = AllocVec (BODYBUFSZ,MEMF_PUBLIC))) return (IFFERR_NOMEM);
  396.  
  397.   error = openifile (&(ilbm->ParseInfo), filename, IFFF_WRITE);
  398.  
  399.   if (! error)
  400.   {
  401.     error = PushChunk (iff, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN);
  402.  
  403.     initbmhd (&ilbm->Bmhd, bitmap, masking, cmpByteRun1, transparentColor, width, height, pagewidth, pageheight, modeid);
  404.  
  405.     CkErr (putbmhd (iff,&ilbm->Bmhd));
  406.  
  407.     if (colortable) CkErr (putcmap (iff,colortable,ncolors,bitspergun));
  408.  
  409.     if (ilbm->IFFPFlags & IFFPF_NOMONITOR) modeid &= (~MONITOR_ID_MASK);
  410.  
  411.     ilbm->camg = modeid;
  412.  
  413.     CkErr (putcamg (iff,&modeid));
  414.  
  415.     /* Write out chunklists 1 & 2 (if any), except for
  416.  
  417.      * any BMHD, CMAP, or CAMG (computed/written separately) */
  418.  
  419.     for (chunk = chunklist1; chunk; chunk = chunk->ch_Next)
  420.     {
  421.       chunkID = chunk->ch_ID;
  422.  
  423.       if ((chunkID != ID_BMHD) && (chunkID != ID_CMAP) && (chunkID != ID_CAMG))
  424.       {
  425.         size = chunk->ch_Size == IFFSIZE_UNKNOWN ? strlen (chunk->ch_Data) : chunk->ch_Size;
  426.  
  427.         CkErr (PutCk (iff, chunkID, size, chunk->ch_Data));
  428.       }
  429.     }
  430.  
  431.     for (chunk = chunklist2; chunk; chunk = chunk->ch_Next)
  432.     {
  433.       chunkID = chunk->ch_ID;
  434.  
  435.       if ((chunkID != ID_BMHD) && (chunkID != ID_CMAP) && (chunkID != ID_CAMG))
  436.       {
  437.         size = chunk->ch_Size == IFFSIZE_UNKNOWN ? strlen (chunk->ch_Data) : chunk->ch_Size;
  438.  
  439.         CkErr (PutCk (iff, chunkID, size, chunk->ch_Data));
  440.       }
  441.     }
  442.  
  443.     /* Write out the BODY */
  444.  
  445.     CkErr (putbody (iff, bitmap, NULL, &ilbm->Bmhd, bodybuf, BODYBUFSZ));
  446.  
  447.     CkErr (PopChunk (iff));    /* close out the FORM */
  448.  
  449.     closeifile (&(ilbm->ParseInfo));    /* and the file */
  450.   }
  451.  
  452.   FreeVec (bodybuf);
  453.  
  454.   return (error);
  455. }
  456.  
  457. /* openifile
  458.  *
  459.  * Passed a ParseInfo structure with a not-in-use IFFHandle, filename
  460.  *   and IFF open mode (IFFF_READ or IFFF_WRITE) opens file for use with
  461.  *   iffparse.library support modules.
  462.  *
  463.  * Returns 0 for success or an IFFERR (libraries/iffparse.h)
  464.  */
  465.  
  466. LONG openifile (struct ParseInfo *pi, UBYTE *filename, ULONG iffopenmode)
  467. {
  468. struct IFFHandle *iff;
  469.  
  470. LONG error = CLIENT_ERROR;
  471.  
  472.   if (! pi) return (error);
  473.  
  474.   if (! (iff = pi->iff)) return (error);
  475.  
  476.   pi->clipboard = FALSE;
  477.  
  478.   /* Set up IFFHandle for buffered stdio I/O. */
  479.  
  480.   if (! (iff->iff_Stream = (ULONG) fopen (filename,omodes [iffopenmode & 1]))) return (NOFILE);
  481.  
  482.   else initiffasstdio (iff);
  483.  
  484.   pi->filename = filename;
  485.  
  486.   error = OpenIFF (iff,iffopenmode);
  487.  
  488.   pi->opened = error ? FALSE : TRUE;    /* currently open handle */
  489.  
  490.   return (error);
  491. }
  492.  
  493. /* closeifile
  494.  *
  495.  * closes file or clipboard opened with openifile, and frees all
  496.  *   iffparse context parsed by parseifile.
  497.  *
  498.  */
  499.  
  500. void closeifile (struct ParseInfo *pi)
  501. {
  502. struct IFFHandle *iff;
  503.  
  504.   if (! pi) return;
  505.  
  506.   if (! (iff = pi->iff)) return;
  507.  
  508.   if (pi->opened) CloseIFF (iff);
  509.  
  510.   if (iff->iff_Stream)
  511.   {
  512.     if (pi->clipboard) CloseClipboard ((struct ClipboardHandle *) (iff->iff_Stream));
  513.  
  514.     else fclose ((FILE *) (iff->iff_Stream));
  515.   }
  516.  
  517.   iff->iff_Stream = NULL;
  518.  
  519.   pi->clipboard = NULL;
  520.  
  521.   pi->opened = NULL;
  522. }
  523.  
  524. /*
  525.  * File I/O hook functions which the IFF library will call.
  526.  * A return of 0 indicates success (no error).
  527.  *
  528.  * Iffparse.library calls this code via struct Hook and Hook.asm
  529.  */
  530. static LONG __saveds __asm stdio_stream (register __a0 struct Hook *hook,register __a2 struct IFFHandle *iff,register __a1 struct IFFStreamCmd *actionpkt)
  531. {
  532. register FILE *stream;
  533. register LONG nbytes;
  534. register LONG actual;
  535. register UBYTE *buf;
  536. LONG len;
  537.  
  538.   stream = (FILE *) iff->iff_Stream;
  539.  
  540.   if (! stream) return (1L);
  541.  
  542.   nbytes = actionpkt->sc_NBytes;
  543.  
  544.   buf = (UBYTE *) actionpkt->sc_Buf;
  545.  
  546.   switch (actionpkt->sc_Command)
  547.   {
  548.     case IFFSCC_READ: do
  549.                       {  actual = (nbytes > 32767 ? 32767 : nbytes);
  550.  
  551.                          if ((len = fread (buf, 1, (size_t) actual, stream)) != actual) break;
  552.  
  553.                          nbytes -= actual;
  554.  
  555.                          buf += actual;
  556.  
  557.                       } while (nbytes > NULL);
  558.  
  559.                       return (nbytes ? IFFERR_READ : NULL);
  560.  
  561.     case IFFSCC_WRITE: do
  562.                        {  actual = (nbytes > 32767 ? 32767 : nbytes);
  563.  
  564.                           if ((len = fwrite (buf, 1, (size_t) actual, stream)) != actual) break;
  565.  
  566.                           nbytes -= actual;
  567.  
  568.                           buf += actual;
  569.  
  570.                        } while (nbytes > NULL);
  571.  
  572.                        return (nbytes ? IFFERR_WRITE : NULL);
  573.  
  574.     case IFFSCC_SEEK:  return ((fseek (stream, nbytes, 1) == -1) ? IFFERR_SEEK : NULL);
  575.  
  576.     default:           return (NULL);  /*  No _INIT or _CLEANUP required.  */
  577.   }
  578. }
  579.  
  580. /* initiffasstdio (ie. init iff as stdio)
  581.  *
  582.  * sets up hook callback for the file stream handler above
  583.  */
  584.  
  585. void initiffasstdio (struct IFFHandle *iff)
  586. {
  587. static struct Hook stdiohook = {{NULL},(ULONG (*)()) stdio_stream,NULL,NULL};
  588.  
  589. /*
  590.  * Initialize the IFF structure to point to the buffered I/O
  591.  * routines.  Unbuffered I/O is terribly slow.
  592.  */
  593.  
  594.   InitIFF (iff, IFFF_FSEEK | IFFF_RSEEK, &stdiohook);
  595. }
  596.  
  597. /* PutCk
  598.  * Writes one chunk of data to an iffhandle
  599.  */
  600.  
  601. LONG PutCk (struct IFFHandle *iff,long id,long size,void *data)
  602. {
  603. LONG error,wlen;
  604.  
  605.   if (! (error = PushChunk (iff,0,id,size)))
  606.   {
  607.      /* Write the actual data */
  608.  
  609.      if ((wlen = WriteChunkBytes (iff,data,size)) != size) error = IFFERR_WRITE;
  610.  
  611.      else error = PopChunk (iff);
  612.   }
  613.  
  614.   return (error);
  615. }
  616.  
  617. /*---------- initbmhd -------------------------------------------------*/
  618.  
  619. LONG initbmhd (BitMapHeader *bmhd, struct BitMap *bitmap,
  620.                WORD masking, WORD compression, WORD transparentColor,
  621.                WORD width, WORD height, WORD pageWidth, WORD pageHeight,
  622.                ULONG modeid)
  623. {
  624.   struct DisplayInfo DI;
  625.  
  626.   if ((! bmhd) || (! bitmap) || (! width) || (! height)) return (CLIENT_ERROR);
  627.  
  628.   bmhd->w = width;
  629.  
  630.   bmhd->h = height;
  631.  
  632.   bmhd->x = bmhd->y = 0;    /* Default position is (0,0).*/
  633.  
  634.   bmhd->nPlanes = bitmap->Depth;
  635.  
  636.   bmhd->masking = masking;
  637.  
  638.   bmhd->compression = compression;
  639.  
  640.   bmhd->flags = BMHDF_CMAPOK;    /* we will store 8 significant bits */
  641.  
  642.   bmhd->transparentColor = transparentColor;
  643.  
  644.   bmhd->pageWidth = pageWidth;
  645.  
  646.   bmhd->pageHeight = pageHeight;
  647.  
  648.   bmhd->xAspect = 0;    /* So we can tell when we've got it */
  649.  
  650.   if (GetDisplayInfoData (NULL, (UBYTE *) &DI, sizeof (struct DisplayInfo), DTAG_DISP, modeid))
  651.   {
  652.      bmhd->xAspect = DI.Resolution.x;
  653.  
  654.      bmhd->yAspect = DI.Resolution.y;
  655.   }
  656.  
  657.     /* If running under 1.3 or GetDisplayInfoData failed, use old method
  658.      * of guessing aspect ratio */
  659.  
  660.   if (! bmhd->xAspect)
  661.   {
  662.     bmhd->xAspect =  44;
  663.  
  664.     bmhd->yAspect = ((struct GfxBase *) GfxBase)->DisplayFlags & PAL ? 44 : 52;
  665.  
  666.     if (modeid & HIRES) bmhd->xAspect = bmhd->xAspect >> 1;
  667.  
  668.     if (modeid & LACE)  bmhd->yAspect = bmhd->yAspect >> 1;
  669.   }
  670.  
  671.   return (IFF_OKAY);
  672. }
  673.  
  674. /*---------- putcmap ---------------------------------------------------*/
  675. /*  This function will accept a table of color values in one of the
  676.  *  following forms:
  677.  *  if bitspergun=4,  colortable is words, each with nibbles 0RGB
  678.  *  if bitspergun=8,  colortable is bytes of RGBRGB etc. (like a CMAP)
  679.  *  if bitspergun=32, colortable is ULONGS of RGBRGB etc.
  680.  *  (only the high eight bits of each gun will be written to CMAP)
  681.  */
  682.  
  683. LONG putcmap (struct IFFHandle *iff,APTR colortable,UWORD ncolors,UWORD bitspergun)
  684. {
  685. LONG error, offs;
  686.  
  687. WORD  *tabw;
  688.  
  689. UBYTE *tab8;
  690.  
  691. ColorRegister cmapReg;
  692.  
  693.   if ((! iff) || (! colortable)) return (CLIENT_ERROR);
  694.  
  695.   /* size of CMAP is 3 bytes * ncolors */
  696.  
  697.   if (error = PushChunk (iff,NULL,ID_CMAP,(LONG) (ncolors * sizeofColorRegister))) return (error);
  698.  
  699.   if (bitspergun == 4)
  700.   {
  701.     /* Store each 4-bit value n as nn */
  702.  
  703.     tabw = (UWORD *) colortable;
  704.  
  705.     for (; ncolors; --ncolors)
  706.     {
  707.       cmapReg.red    = ( *tabw >> 4 ) & 0xf0;
  708.  
  709.       cmapReg.red   |= (cmapReg.red >> 4);
  710.  
  711.       cmapReg.green  = ( *tabw      ) & 0xf0;
  712.  
  713.       cmapReg.green |= (cmapReg.green >> 4);
  714.  
  715.       cmapReg.blue   = ( *tabw << 4 ) & 0xf0;
  716.  
  717.       cmapReg.blue  |= (cmapReg.blue >> 4);
  718.  
  719.       if ((WriteChunkBytes (iff,(BYTE *) &cmapReg,sizeofColorRegister)) != sizeofColorRegister) return (IFFERR_WRITE);
  720.  
  721.       ++tabw;
  722.     }
  723.   }
  724.  
  725.   else
  726.  
  727.     if ((bitspergun == 8) || (bitspergun == 32))
  728.     {
  729.       tab8 = (UBYTE *) colortable;
  730.  
  731.       offs = (bitspergun == 8) ? 1 : 4;
  732.  
  733.       for ( ;  ncolors;  --ncolors )
  734.       {
  735.         cmapReg.red   = *tab8;
  736.  
  737.         tab8 += offs;
  738.  
  739.         cmapReg.green = *tab8;
  740.  
  741.         tab8 += offs;
  742.  
  743.         cmapReg.blue  = *tab8;
  744.  
  745.         tab8 += offs;
  746.  
  747.         if ((WriteChunkBytes (iff,(BYTE *) &cmapReg,sizeofColorRegister)) != sizeofColorRegister) return (IFFERR_WRITE);
  748.       }
  749.     }
  750.  
  751.   error = PopChunk (iff);
  752.  
  753.   return (error);
  754. }
  755.  
  756. /*---------- putbody ---------------------------------------------------*/
  757. /* NOTE: This implementation could be a LOT faster if it used more of the
  758.  * supplied buffer. It would make far fewer calls to IFFWriteBytes (and
  759.  * therefore to DOS Write).
  760.  *
  761.  * Incorporates modification by Jesper Steen Moller to accept source
  762.  * rows wider than dest rows, with one modulo variable for source bitplane
  763.  * rows and one for the ILBM bitmap rows.
  764.  */
  765.  
  766. LONG putbody (struct IFFHandle *iff, struct BitMap *bitmap, BYTE *mask,BitMapHeader *bmhd, BYTE *buffer, LONG bufsize)
  767. {
  768. LONG error;
  769.  
  770. LONG rowBytes = bitmap->BytesPerRow;   /* for source modulo only */
  771.  
  772. LONG FileRowBytes = RowBytes (bmhd->w); /* width to write in bytes */
  773.  
  774. int dstDepth = bmhd->nPlanes;
  775.  
  776. UBYTE compression = bmhd->compression;
  777.  
  778. int planeCnt;                          /* number of bit planes including mask */
  779.  
  780. register int iPlane, iRow;
  781.  
  782. register LONG packedRowBytes;
  783.  
  784. BYTE *buf;
  785.  
  786. BYTE *planes [MAXSAVEDEPTH + 1];        /* array of ptrs to planes & mask */
  787.  
  788.   if ( bufsize < MaxPackedSize (FileRowBytes) ||  /* Must buffer a comprsd row*/
  789.  
  790.        compression > cmpByteRun1              ||  /* bad arg */
  791.  
  792.        bitmap->Rows != bmhd->h                ||  /* inconsistent */
  793.  
  794.        rowBytes < FileRowBytes                ||  /* inconsistent*/
  795.  
  796.        bitmap->Depth < dstDepth               ||  /* inconsistent */
  797.  
  798.        dstDepth > MAXSAVEDEPTH )                  /* too many for this routine*/
  799.  
  800.     return (CLIENT_ERROR);
  801.  
  802.   planeCnt = dstDepth + (mask == NULL ? 0 : 1);
  803.  
  804.   /* Copy the ptrs to bit & mask planes into local array "planes" */
  805.  
  806.   for (iPlane = 0; iPlane < dstDepth; iPlane++) planes [iPlane] = (BYTE *) bitmap->Planes [iPlane];
  807.  
  808.   if (mask != NULL) planes [dstDepth] = mask;
  809.  
  810.   /* Write out a BODY chunk header */
  811.  
  812.   if (error = PushChunk (iff, NULL, ID_BODY, IFFSIZE_UNKNOWN)) return (error);
  813.  
  814.   /* Write out the BODY contents */
  815.  
  816.   for (iRow = bmhd->h; iRow > 0; iRow--)
  817.   {
  818.     for (iPlane = 0; iPlane < planeCnt; iPlane++)
  819.     {
  820.       /* Write next row.*/
  821.  
  822.       if (compression == cmpNone)
  823.       {
  824.         if (WriteChunkBytes (iff,planes [iPlane],FileRowBytes) != FileRowBytes) error = IFFERR_WRITE;
  825.  
  826.         planes [iPlane] += rowBytes; /* Possibly skipping unused bytes */
  827.       }
  828.  
  829.       else                     /* Compress and write next row.*/
  830.       {
  831.         buf = buffer;
  832.  
  833.         packedRowBytes = PackRow (&planes [iPlane], &buf, FileRowBytes);
  834.  
  835.         /* Note that packrow incremented planes already by FileRowBytes */
  836.  
  837.         planes [iPlane] += rowBytes-FileRowBytes; /* Possibly skipping unused bytes */
  838.  
  839.         if (WriteChunkBytes (iff,buffer,packedRowBytes) != packedRowBytes) error = IFFERR_WRITE;
  840.       }
  841.  
  842.       if (error) return (error);
  843.     }
  844.   }
  845.  
  846.   /* Finish the chunk */
  847.  
  848.   error = PopChunk (iff);
  849.  
  850.   return (error);
  851. }
  852.  
  853. LONG loadcmap (struct ILBMInfo *ilbm)
  854. {
  855. struct StoredProperty *sp;
  856.  
  857. struct IFFHandle *iff;
  858.  
  859. BOOL AllShifted;
  860.  
  861. UBYTE *rgb, rb, gb, bb;
  862.  
  863. LONG k;
  864.  
  865. ULONG ncolors, gun, ncheck, nc, r, g, b;
  866.  
  867.   if (! (iff = ilbm->ParseInfo.iff)) return (CLIENT_ERROR);
  868.  
  869.   if (! (ilbm->colortable)) return (1L);
  870.  
  871.   if (! (sp = FindProp (iff, ID_ILBM, ID_CMAP))) return (1L);
  872.  
  873.   rgb = sp->sp_Data;
  874.  
  875.   /* file has this many colors */
  876.  
  877.   nc = sp->sp_Size / sizeofColorRegister;
  878.  
  879.   ncolors = nc;
  880.  
  881.   /* if ILBMInfo can't hold that many, we'll load less */
  882.  
  883.   if (ilbm->ncolors < ncolors) ncolors = ilbm->ncolors;
  884.  
  885.   /* set to how many we are loading */
  886.  
  887.   ilbm->ncolors = ncolors;
  888.  
  889.   /* how many colors to check for shifted nibbles (i.e. used colors) */
  890.  
  891.   ncheck = 1L << ilbm->Bmhd.nPlanes;
  892.  
  893.   if (ncheck > ncolors) ncheck = ncolors;
  894.  
  895.   if ((! (ilbm->IFFPFlags & IFFPF_NOCOLOR32)) && (ilbm->colorrecord))
  896.   {
  897.     ilbm->colorrecord [0] = ncolors << 16L;
  898.  
  899.     /* Assign to 32-bit table, examine for all-shifted nibbles at same time */
  900.  
  901.     AllShifted = TRUE;
  902.  
  903.     k = 0;
  904.  
  905.     while (ncheck--)
  906.     {
  907.       ilbm->colortable32 [k].r = rb = *rgb++;
  908.  
  909.       ilbm->colortable32 [k].g = gb = *rgb++;
  910.  
  911.       ilbm->colortable32 [k].b = bb = *rgb++;
  912.  
  913.       if (((rb & 0x0F) || (gb & 0x0F) || (bb & 0x0F))) AllShifted = FALSE;
  914.  
  915.       k++;
  916.     }
  917.  
  918.     /* If no file/user indication that this is an 8-bit significant CMAP... */
  919.  
  920.     if ((! (ilbm->IFFPFlags & IFFPF_CMAPOK)) &&    (! (ilbm->Bmhd.flags & BMHDF_CMAPOK)))
  921.     {
  922.       /* If all nibbles appear shifted (4 bit), duplicate the nibbles */
  923.  
  924.       if (AllShifted)
  925.       {
  926.         for (k = 0; k < nc; k++)
  927.         {
  928.           ilbm->colortable32 [k].r |= (ilbm->colortable32 [k].r >> 4);
  929.  
  930.           ilbm->colortable32 [k].g |= (ilbm->colortable32 [k].g >> 4);
  931.  
  932.           ilbm->colortable32 [k].b |= (ilbm->colortable32 [k].b >> 4);
  933.         }
  934.       }
  935.     }
  936.  
  937.     /* Now scale to 32 bits */
  938.  
  939.     for (k = 0; k < nc; k++)
  940.     {
  941.       gun = ilbm->colortable32 [k].r;
  942.  
  943.       ilbm->colortable32 [k].r |= ((gun << 24) | (gun << 16) | (gun << 8));
  944.  
  945.       gun = ilbm->colortable32 [k].g;
  946.  
  947.       ilbm->colortable32 [k].g |= ((gun << 24) | (gun << 16) | (gun << 8));
  948.  
  949.       gun = ilbm->colortable32 [k].b;
  950.  
  951.       ilbm->colortable32 [k].b |= ((gun << 24) | (gun << 16) | (gun << 8));
  952.     }
  953.   }
  954.  
  955.   /* always make old-style table */
  956.  
  957.   rgb = sp->sp_Data;
  958.  
  959.   ncolors = nc;
  960.  
  961.   k = 0;
  962.  
  963.   while (ncolors--)
  964.   {
  965.     r = (*rgb++ & 0xF0) << 4;
  966.  
  967.     g = *rgb++ & 0xF0;
  968.  
  969.     b = *rgb++ >> 4;
  970.  
  971.     ilbm->colortable [k] = r | g | b;
  972.  
  973.     k++;
  974.   }
  975.  
  976.   return (NULL);
  977. }
  978.  
  979. LONG getcolors (struct ILBMInfo *ilbm)
  980. {
  981. struct IFFHandle *iff;
  982.  
  983. LONG error = CLIENT_ERROR;
  984.  
  985.   if (! (iff = ilbm->ParseInfo.iff)) return (error);
  986.  
  987.   if (! (error = alloccolortable (ilbm))) error = loadcmap (ilbm);
  988.  
  989.   if (error) freecolors (ilbm);
  990.  
  991.   return (error);
  992. }
  993.  
  994. /* alloccolortable - allocates ilbm->colortable and sets ilbm->ncolors
  995.  *    to the number of colors we have room for in the table.
  996.  *
  997.  * V39 and above: unless ilbm->IFFPFlags & IFFPF_NOCOLOR32, will also
  998.  *  allocate and build a 32-bit per gun colortable (ilbm->colortable32)
  999.  *  and ilbm->colorrecord for LoadRGB32()
  1000.  */
  1001.  
  1002. LONG alloccolortable (struct ILBMInfo *ilbm)
  1003. {
  1004. struct IFFHandle *iff;
  1005.  
  1006. struct StoredProperty *sp;
  1007.  
  1008. LONG error = NULL;
  1009.  
  1010. ULONG ctabsize;
  1011.  
  1012. UWORD ncolors;
  1013.  
  1014.   if (! (iff = ilbm->ParseInfo.iff)) return (CLIENT_ERROR);
  1015.  
  1016.   if (sp = FindProp (iff,ID_ILBM,ID_CMAP))
  1017.   {
  1018.      /*
  1019.       * Compute the size table we need
  1020.       */
  1021.  
  1022.      ncolors = sp->sp_Size / 3;        /* how many in CMAP */
  1023.  
  1024.      ncolors = MAX (ncolors,16);    /* alloc at least 16 */
  1025.  
  1026.      ctabsize = ncolors * sizeof (Color4);
  1027.  
  1028.      if (ilbm->colortable = (Color4 *) AllocVec (ctabsize,MEMF_PUBLIC | MEMF_CLEAR))
  1029.      {
  1030.     ilbm->ncolors = ncolors;
  1031.  
  1032.     ilbm->ctabsize = ctabsize;
  1033.  
  1034.         if ((! (ilbm->IFFPFlags & IFFPF_NOCOLOR32)))
  1035.     {
  1036.            ctabsize = (ncolors * sizeof (Color32)) + (2 * sizeof (LONG));
  1037.  
  1038.        if (ilbm->colorrecord = (ULONG *) AllocVec (ctabsize,MEMF_PUBLIC | MEMF_CLEAR))
  1039.            {
  1040.           ilbm->crecsize = ctabsize;
  1041.  
  1042.           ilbm->colortable32 = (Color32 *) (&ilbm->colorrecord [1L]);
  1043.  
  1044.           ilbm->colorrecord [0L] = ncolors << 16L;     /* For LoadRGB32 */
  1045.  
  1046.               ilbm->colorrecord [ncolors * sizeof (Color32) + 1L] = NULL;
  1047.            }
  1048.  
  1049.            else error = IFFERR_NOMEM;
  1050.         }
  1051.      }
  1052.  
  1053.      else error = IFFERR_NOMEM;
  1054.   }
  1055.  
  1056.   if (error) freecolors (ilbm);
  1057.  
  1058.   return (error);
  1059. }
  1060.  
  1061. VOID freecolors (struct ILBMInfo *ilbm)
  1062. {
  1063.    if (ilbm->colortable) FreeVec (ilbm->colortable);
  1064.  
  1065.    ilbm->colortable = NULL;
  1066.  
  1067.    ilbm->ctabsize = 0;
  1068.  
  1069.    if (ilbm->colorrecord) FreeVec (ilbm->colorrecord);
  1070.  
  1071.    ilbm->colorrecord  = NULL;
  1072.  
  1073.    ilbm->colortable32 = NULL;
  1074.  
  1075.    ilbm->crecsize = 0;
  1076. }
  1077.  
  1078. LONG currentchunkis (struct IFFHandle *iff,LONG type,LONG id)
  1079. {
  1080. register struct ContextNode *cn;
  1081.  
  1082. LONG result = 0;
  1083.  
  1084.   if (cn = CurrentChunk (iff))
  1085.  
  1086.     if ((cn->cn_Type == type) && (cn->cn_ID == id)) result = 1;
  1087.  
  1088.   return (result);
  1089. }
  1090.  
  1091. /*---------- loadbody ---------------------------------------------------*/
  1092.  
  1093. LONG loadbody (struct IFFHandle *iff,struct BitMap *bitmap,BitMapHeader *bmhd)
  1094. {
  1095. BYTE *buffer;
  1096.  
  1097. ULONG bufsize;
  1098.  
  1099. LONG error = 1L;
  1100.  
  1101.   if (! (currentchunkis (iff,ID_ILBM,ID_BODY))) return (IFF_OKAY);
  1102.  
  1103.   if ((bitmap) && (bmhd))
  1104.   {
  1105.      bufsize = MaxPackedSize (RowBytes (bmhd->w)) << 4L;
  1106.  
  1107.      if (! (buffer = AllocVec (bufsize,0L))) return (IFFERR_NOMEM);
  1108.  
  1109.      error = loadbody2 (iff,bitmap,NULL,bmhd,buffer,bufsize);
  1110.  
  1111.      FreeVec (buffer);
  1112.   }
  1113.  
  1114.   return (error);
  1115. }
  1116.  
  1117. LONG loadbody2 (struct IFFHandle *iff,struct BitMap *bitmap,BYTE *mask,BitMapHeader *bmhd,BYTE *buffer,ULONG bufsize)
  1118. {
  1119. UBYTE srcPlaneCnt = bmhd->nPlanes;   /* Haven't counted for mask plane yet*/
  1120.  
  1121. WORD srcRowBytes = RowBytes (bmhd->w);
  1122.  
  1123. WORD destRowBytes = bitmap->BytesPerRow;   /* used as a modulo only */
  1124.  
  1125. LONG bufRowBytes = MaxPackedSize (srcRowBytes);
  1126.  
  1127. WORD nRows = bmhd->h;
  1128.  
  1129. WORD destWidthBytes;            /* used for width check */
  1130.  
  1131. WORD compression = bmhd->compression;
  1132.  
  1133. register WORD iPlane, iRow, nEmpty;
  1134.  
  1135. register WORD nFilled;
  1136.  
  1137. BYTE *buf, *nullDest, *nullBuf, **pDest;
  1138.  
  1139. BYTE *planes [MaxSrcPlanes]; /* array of ptrs to planes & mask */
  1140.  
  1141. struct ContextNode *cn;
  1142.  
  1143.    cn = CurrentChunk (iff);
  1144.  
  1145.    if (compression > cmpByteRun1) return (CLIENT_ERROR);
  1146.  
  1147.    /* If >=V39, this may be an interleaved bitmap with a BytesPerRow
  1148.     * which is truly just a modulo and actually includes ALL planes.
  1149.     * So instead, for bounds checking, we use the pixel width of
  1150.     * the BitMap rounded up to nearest WORD, since saved ILBMs
  1151.     * are always saved as their width rounded up to nearest WORD.
  1152.     */
  1153.  
  1154.    destWidthBytes = RowBytes (GetBitMapAttr (bitmap,BMA_WIDTH));
  1155.  
  1156.    /* Complain if client asked for a conversion GetBODY doesn't handle.*/
  1157.  
  1158.    if (srcRowBytes > destWidthBytes || bufsize < (bufRowBytes * 2) || srcPlaneCnt > MaxSrcPlanes) return (CLIENT_ERROR);
  1159.  
  1160.    if (nRows > bitmap->Rows) nRows = bitmap->Rows;
  1161.  
  1162.    /* Initialize array "planes" with bitmap ptrs; NULL in empty slots.*/
  1163.  
  1164.    for (iPlane = 0; iPlane < bitmap->Depth; iPlane++) planes [iPlane] = (BYTE *) bitmap->Planes [iPlane];
  1165.  
  1166.    for ( ; iPlane < MaxSrcPlanes; iPlane++) planes [iPlane] = NULL;
  1167.  
  1168.    /* Copy any mask plane ptr into corresponding "planes" slot.*/
  1169.  
  1170.    if (bmhd->masking == mskHasMask)
  1171.    {
  1172.       if (mask) planes [srcPlaneCnt] = mask;  /* If there are more srcPlanes than
  1173.  
  1174.                                                * dstPlanes, there will be NULL plane-pointers before this. */
  1175.  
  1176.       else  planes [srcPlaneCnt] = NULL;  /* In case more dstPlanes than src. */
  1177.  
  1178.       srcPlaneCnt += 1;  /* Include mask plane in count.*/
  1179.    }
  1180.  
  1181.    /* Setup a sink for dummy destination of rows from unwanted planes.*/
  1182.  
  1183.    nullDest = buffer;
  1184.  
  1185.    buffer  += srcRowBytes;
  1186.  
  1187.    bufsize -= srcRowBytes;
  1188.  
  1189.    /* Read the BODY contents into client's bitmap.
  1190.     * De-interleave planes and decompress rows.
  1191.     * MODIFIES: Last iteration modifies bufsize.*/
  1192.  
  1193.    buf = buffer + bufsize;  /* Buffer is currently empty.*/
  1194.  
  1195.    for (iRow = nRows; iRow > 0; iRow--)
  1196.    {
  1197.        for (iPlane = 0; iPlane < srcPlaneCnt; iPlane++)
  1198.        {
  1199.          pDest = &planes [iPlane];
  1200.  
  1201.             /* Establish a sink for any unwanted plane.*/
  1202.  
  1203.             if (*pDest == NULL)
  1204.             {
  1205.             nullBuf = nullDest;
  1206.  
  1207.                 pDest   = &nullBuf;
  1208.             }
  1209.  
  1210.             /* Read in at least enough bytes to uncompress next row.*/
  1211.  
  1212.             nEmpty  = buf - buffer;      /* size of empty part of buffer.*/
  1213.  
  1214.             nFilled = bufsize - nEmpty;      /* this part has data.*/
  1215.  
  1216.         if (nFilled < bufRowBytes)
  1217.             {
  1218.             /* Need to read more.*/
  1219.             /* Move the existing data to the front of the buffer.*/
  1220.             /* Now covers range buffer[0]..buffer[nFilled-1].*/
  1221.  
  1222.                 movmem (buf,buffer,nFilled);  /* Could be moving 0 bytes.*/
  1223.  
  1224.                 if (nEmpty > ChunkMoreBytes (cn))
  1225.         {
  1226.                        /* There aren't enough bytes left to fill the buffer.*/
  1227.  
  1228.                      nEmpty = ChunkMoreBytes (cn);
  1229.  
  1230.                        bufsize = nFilled + nEmpty;  /* heh-heh */
  1231.                    }
  1232.  
  1233.             /* Append new data to the existing data.*/
  1234.  
  1235.                 if (ReadChunkBytes (iff,&buffer [nFilled],(LONG) nEmpty) < nEmpty) return (CLIENT_ERROR);
  1236.  
  1237.                 buf = buffer;
  1238.  
  1239.             nFilled = bufsize;
  1240.             }
  1241.  
  1242.          /* Copy uncompressed row to destination plane.*/
  1243.  
  1244.             if (compression == cmpNone)
  1245.             {
  1246.                 if (nFilled < srcRowBytes)  return (IFFERR_MANGLED);
  1247.  
  1248.             movmem (buf,*pDest,srcRowBytes);
  1249.  
  1250.             buf    += srcRowBytes;
  1251.  
  1252.                 *pDest += destRowBytes;
  1253.             }
  1254.  
  1255.         else
  1256.             {
  1257.              /* Decompress row to destination plane.*/
  1258.  
  1259.                 if (UnPackRow (&buf,pDest,nFilled,srcRowBytes)) return (IFFERR_MANGLED);
  1260.  
  1261.                            /*  pSource, pDest, srcBytes, dstBytes  */
  1262.  
  1263.             else *pDest += (destRowBytes - srcRowBytes);
  1264.  
  1265.             }
  1266.     }
  1267.    }
  1268.  
  1269.    return (IFF_OKAY);
  1270. }
  1271.  
  1272. ULONG getcamg (struct ILBMInfo *ilbm)
  1273. {
  1274. struct IFFHandle *iff;
  1275.  
  1276. struct StoredProperty *sp;
  1277.  
  1278. UWORD wide,high,deep;
  1279.  
  1280. ULONG modeid = NULL;
  1281.  
  1282.   if (! (iff = ilbm->ParseInfo.iff)) return (NULL);
  1283.  
  1284.   wide = ilbm->Bmhd.pageWidth;
  1285.  
  1286.   high = ilbm->Bmhd.pageHeight;
  1287.  
  1288.   deep = ilbm->Bmhd.nPlanes;
  1289.  
  1290.   /* Grab CAMG's idea of the viewmodes */
  1291.  
  1292.   if (sp = FindProp (iff, ID_ILBM, ID_CAMG))
  1293.   {
  1294.      modeid = (* (ULONG *) sp->sp_Data);
  1295.  
  1296.      /* knock bad bits out of old-style 16-bit viewmode CAMGs */
  1297.  
  1298.      if ((! (modeid & MONITOR_ID_MASK)) || ((modeid & EXTENDED_MODE) && (! (modeid & 0xFFFF0000)))) modeid &= (~(EXTENDED_MODE | SPRITES | GENLOCK_AUDIO | GENLOCK_VIDEO | VP_HIDE));
  1299.  
  1300.      /* check for bogus CAMG like DPaintII brushes
  1301.       * with junk in upper word and extended bit
  1302.       * not set in lower word.
  1303.       */
  1304.  
  1305.      if ((modeid & 0xFFFF0000) && (! (modeid & 0x00001000))) sp = NULL;
  1306.   }
  1307.  
  1308.   if (! sp)
  1309.   {
  1310.      /*
  1311.       * No CAMG (or bad CAMG) present; use computed modes.
  1312.       */
  1313.  
  1314.      modeid = NULL;        /* added in 39.6 */
  1315.  
  1316.      if (wide >= 640) modeid = HIRES;
  1317.  
  1318.      if (high >= 400) modeid |= LACE;
  1319.  
  1320.      if (deep == 6)
  1321.      {
  1322.         modeid |= ilbm->EHB ? EXTRA_HALFBRITE : HAM;
  1323.      }
  1324.   }
  1325.  
  1326.   if (ilbm->IFFPFlags & IFFPF_NOMONITOR) modeid &= (~MONITOR_ID_MASK);
  1327.  
  1328.   return (modeid);
  1329. }
  1330.  
  1331. LONG chkcnt (LONG *TaggedArray)
  1332. {
  1333. LONG k = 0;
  1334.  
  1335.   while (TaggedArray [k] != TAG_END) k++;
  1336.  
  1337.   return (k >> 1);
  1338. }
  1339.  
  1340. LONG getcontext (struct IFFHandle *iff)
  1341. {
  1342. LONG error;
  1343.  
  1344.   /* Based on our parse initialization, ParseIFF() will return on a stop chunk
  1345.    * (error = 0) or end of context for an ILBM FORM (error = IFFERR_EOC) or end of
  1346.    * file (error = IFFERR_EOF)
  1347.    */
  1348.  
  1349.   return (error = ParseIFF (iff,IFFPARSE_SCAN));
  1350. }
  1351.  
  1352. LONG parseifile (struct    ParseInfo *pi,LONG groupid,LONG grouptype,LONG *propchks,LONG *collectchks,LONG *stopchks)
  1353. {
  1354. struct IFFHandle *iff;
  1355.  
  1356. register struct ContextNode *cn;
  1357.  
  1358. LONG error;
  1359.  
  1360.   if (! (iff = pi->iff)) return (CLIENT_ERROR);
  1361.  
  1362.   if (! iff->iff_Stream) return (IFFERR_READ);
  1363.  
  1364.   pi->hunt = FALSE;
  1365.  
  1366.   /* Declare property, collection and stop chunks.*/
  1367.  
  1368.   if (propchks)
  1369.  
  1370.       if (error = PropChunks (iff, propchks, chkcnt (propchks))) return (error);
  1371.  
  1372.   if (collectchks)
  1373.  
  1374.           if (error = CollectionChunks (iff, collectchks, chkcnt (collectchks))) return (error);
  1375.  
  1376.   if (stopchks)
  1377.  
  1378.           if (error = StopChunks (iff, stopchks, chkcnt (stopchks))) return (error);
  1379.  
  1380.     /* We want to stop at the end of an ILBM context. */
  1381.  
  1382.   if (grouptype)
  1383.  
  1384.       if (error = StopOnExit (iff, grouptype, groupid)) return (error);
  1385.  
  1386.     /* Take first parse step to enter main chunk. */
  1387.  
  1388.   if (error = ParseIFF (iff,IFFPARSE_STEP)) return (error);
  1389.  
  1390.     /* Test the chunk info to see if simple form of type we want (ILBM).*/
  1391.  
  1392.   if (! (cn = CurrentChunk (iff))) return (NOFILE); /* This really should never happen.  If it does, it means our parser is broken. */
  1393.  
  1394.   if (cn->cn_ID != groupid || cn->cn_Type != grouptype) pi->hunt = TRUE; /* Warning - this is a complex file */
  1395.  
  1396.   if (! error) error = getcontext (iff);
  1397.  
  1398.   return (error);
  1399. }
  1400.  
  1401. LONG contextis (struct IFFHandle *iff,LONG type,LONG id)
  1402. {
  1403. register struct ContextNode *cn;
  1404.  
  1405. LONG result = NULL;
  1406.  
  1407.   if (cn = (CurrentChunk (iff)))
  1408.   {
  1409.     if (cn = (ParentChunk (cn)))
  1410.     {
  1411.       if ((cn->cn_Type == type) && (cn->cn_ID == id)) result = 1L;
  1412.     }
  1413.   }
  1414.  
  1415.   return (result);
  1416. }
  1417.  
  1418. UBYTE *findpropdata (struct IFFHandle *iff,LONG type,LONG id)
  1419. {
  1420. register struct StoredProperty *sp;
  1421.  
  1422.   if (sp = FindProp (iff,type,id)) return (sp->sp_Data);
  1423.  
  1424.   return (0);
  1425. }
  1426.  
  1427. LONG setcolors (struct ILBMInfo *ilbm,struct ViewPort *vp)
  1428. {
  1429. LONG ncolors;
  1430.  
  1431.   if (! vp) return (CLIENT_ERROR);
  1432.  
  1433.   ncolors = MIN (ilbm->ncolors,vp->ColorMap->Count);
  1434.  
  1435.   if ((! (ilbm->IFFPFlags & IFFPF_NOCOLOR32)) && (ilbm->colorrecord))
  1436.  
  1437.      Fade (ilbm->win,ilbm->colorrecord,25L,1L,FROMBLACK);
  1438.  
  1439.   else
  1440.  
  1441.      if (ilbm->colortable) LoadRGB4 (vp,(UWORD *) ilbm->colortable,ncolors);
  1442.  
  1443.   return (NULL);
  1444. }
  1445.  
  1446. /**********  ByteRun1 ***************************************************/
  1447.  
  1448. static BYTE *PutDump (BYTE *dest, int nn)
  1449. {
  1450.   LONG i;
  1451.  
  1452.   PutByte (nn-1);
  1453.  
  1454.   for (i = 0;  i < nn;  i++) PutByte (PackBuffer [i]);
  1455.  
  1456.   return (dest);
  1457. }
  1458.  
  1459. static BYTE *PutRun (BYTE *dest, int nn, int cc)
  1460. {
  1461.   PutByte (-(nn-1));
  1462.  
  1463.   PutByte (cc);
  1464.  
  1465.   return( dest);
  1466. }
  1467.  
  1468. /*----------- packrow --------------------------------------------------*/
  1469.  
  1470. /* Given POINTERS TO POINTERS, packs one row, updating the source and
  1471.  * destination pointers.  RETURNs count of packed bytes. */
  1472.  
  1473. LONG PackRow (BYTE **pSource, BYTE **pDest, LONG rowSize)
  1474. {
  1475. BYTE *source, *dest;
  1476. char c,lastc;
  1477. BOOL mode = DUMP;
  1478. WORD nbuf;       /* number of chars in buffer */
  1479. WORD rstart = 0; /* buffer index current run starts */
  1480.  
  1481.   source = *pSource;
  1482.  
  1483.   dest = *pDest;
  1484.  
  1485.   PackPutSize = 0;
  1486.  
  1487.   PackBuffer [0] = lastc = c = GetByte ();  /* so have valid lastc */
  1488.  
  1489.   nbuf = 1;   rowSize--;    /* since one byte eaten.*/
  1490.  
  1491.   for (;  rowSize;  --rowSize)
  1492.   {
  1493.     PackBuffer [nbuf++] = c = GetByte ();
  1494.  
  1495.     switch (mode)
  1496.     {
  1497.       case DUMP:
  1498.  
  1499.         /* If the buffer is full, write the length byte, then the data */
  1500.         if (nbuf>MaxDat)
  1501.         {
  1502.           OutDump(nbuf-1);
  1503.           PackBuffer[0] = c;
  1504.           nbuf = 1;
  1505.           rstart = 0;
  1506.           break;
  1507.         }
  1508.  
  1509.         if (c == lastc)
  1510.         {
  1511.           if (nbuf-rstart >= MinRun)
  1512.           {
  1513.             if (rstart > 0)
  1514.               OutDump(rstart);
  1515.             mode = RUN;
  1516.           }
  1517.           else
  1518.             if (rstart == 0)
  1519.               mode = RUN; /* no dump in progress, so can't lose by making these 2 a run.*/
  1520.         }
  1521.         else
  1522.           rstart = nbuf-1;        /* first of run */
  1523.         break;
  1524.  
  1525.       case RUN:
  1526.  
  1527.         if ( (c != lastc)|| ( nbuf-rstart > MaxRun))
  1528.         {
  1529.           /* output run */
  1530.           OutRun(nbuf-1-rstart,lastc);
  1531.           PackBuffer[0] = c;
  1532.           nbuf = 1;
  1533.           rstart = 0;
  1534.           mode = DUMP;
  1535.         }
  1536.         break;
  1537.     }
  1538.  
  1539.     lastc = c;
  1540.   }
  1541.  
  1542.   switch (mode)
  1543.   {
  1544.     case DUMP: OutDump (nbuf);
  1545.  
  1546.                break;
  1547.  
  1548.     case RUN:  OutRun (nbuf-rstart,lastc);
  1549.  
  1550.                break;
  1551.   }
  1552.  
  1553.   *pSource = source;
  1554.  
  1555.   *pDest = dest;
  1556.  
  1557.   return (PackPutSize);
  1558. }
  1559.  
  1560. BOOL UnPackRow (BYTE **pSource, BYTE **pDest, WORD srcBytes0, WORD dstBytes0)
  1561. {
  1562.   register BYTE *source = *pSource;
  1563.   register BYTE *dest   = *pDest;
  1564.   register WORD n;
  1565.   register WORD srcBytes = srcBytes0;
  1566.   register WORD dstBytes = dstBytes0;
  1567.   BOOL error = TRUE;    /* assume error until we make it through the loop */
  1568.   WORD minus128 = -128;  /* get the compiler to generate a CMP.W */
  1569.   register BYTE c;
  1570.  
  1571.   while( dstBytes > 0 )
  1572.   {
  1573.     if ( (srcBytes -= 1) < 0 )
  1574.     {
  1575.       *pSource = source;
  1576.       *pDest = dest;
  1577.       return(error);
  1578.     }
  1579.     n = UGetByte();
  1580.  
  1581.     if (n >= 0)
  1582.     {
  1583.       n += 1;
  1584.       if ( (srcBytes -= n) < 0 )
  1585.       {
  1586.         *pSource = source;
  1587.         *pDest = dest;
  1588.         return(error);
  1589.       }
  1590.       if ( (dstBytes -= n) < 0 )
  1591.       {
  1592.         *pSource = source;
  1593.         *pDest = dest;
  1594.         return(error);
  1595.       }
  1596.       do
  1597.       {
  1598.         UPutByte(UGetByte());
  1599.       } while (--n > 0);
  1600.     }
  1601.     else
  1602.     if (n != minus128)
  1603.     {
  1604.       n = -n + 1;
  1605.       if ( (srcBytes -= 1) < 0 )
  1606.       {
  1607.         *pSource = source;
  1608.         *pDest = dest;
  1609.         return(error);
  1610.       }
  1611.       if ( (dstBytes -= n) < 0 )
  1612.       {
  1613.         *pSource = source;
  1614.         *pDest = dest;
  1615.         return(error);
  1616.       }
  1617.       c = UGetByte();
  1618.       do
  1619.       {
  1620.         UPutByte(c);
  1621.       } while (--n > 0);
  1622.     }
  1623.   }
  1624.   error = FALSE;    /* success! */
  1625.   *pSource = source;
  1626.   *pDest = dest;
  1627.   return(error);
  1628. }
  1629.  
  1630. /*----------------------------------------------------------------------*/
  1631.  
  1632. /* queryilbm
  1633.  *
  1634.  * Passed an initilized ILBMInfo with a not-in-use IFFHandle,
  1635.  *   and a filename,
  1636.  *   will open an ILBM, fill in ilbm->camg and ilbm->bmhd,
  1637.  *   and close the ILBM.
  1638.  *
  1639.  * This allows you to determine if the ILBM is a size and
  1640.  *   type you want to deal with.
  1641.  *
  1642.  * Returns 0 for success or an IFFERR (libraries/iffparse.h)
  1643.  */
  1644.  
  1645. LONG QueryMandPic (struct ILBMInfo *ilbm,struct MandelChunk **ManChk,UBYTE *filename)
  1646. {
  1647. LONG error;
  1648.  
  1649. BitMapHeader *bmhd;
  1650.  
  1651.   if (! (ilbm->ParseInfo.iff)) return (CLIENT_ERROR);
  1652.  
  1653.   error = openifile (&(ilbm->ParseInfo),filename,IFFF_READ);
  1654.  
  1655.   if (! error)
  1656.   {
  1657.      error = parseifile (&(ilbm->ParseInfo),ID_FORM,ID_ILBM,ilbm->ParseInfo.propchks,ilbm->ParseInfo.collectchks,ilbm->ParseInfo.stopchks);
  1658.  
  1659.      if ((! error) || (error == IFFERR_EOC) || (error == IFFERR_EOF))
  1660.      {
  1661.     if (contextis (ilbm->ParseInfo.iff,ID_ILBM,ID_FORM))
  1662.     {
  1663.        if (*ManChk = (struct MandelChunk *) findpropdata (ilbm->ParseInfo.iff,ID_ILBM,ID_MAND))
  1664.        {
  1665.               if (bmhd = (BitMapHeader *) findpropdata (ilbm->ParseInfo.iff,ID_ILBM,ID_BMHD))
  1666.               {
  1667.                  *(&ilbm->Bmhd) = *bmhd;
  1668.  
  1669.                  ilbm->camg = getcamg (ilbm);
  1670.               }
  1671.  
  1672.               else error = NOFILE;
  1673.        }
  1674.  
  1675.        else error = NOMAND;
  1676.     }
  1677.  
  1678.     else error = NOFILE;
  1679.      }
  1680.  
  1681.      closeifile (&(ilbm->ParseInfo));
  1682.   }
  1683.  
  1684.   return (error);
  1685. }
  1686.  
  1687. /* LoadMandPic
  1688.  *
  1689.  * Passed a not-in-use IFFHandle, an initialized ILBMInfo, and filename,
  1690.  *   will load an ILBM into your already opened ilbm->scr, setting up
  1691.  *   ilbm->Bmhd, ilbm->camg, ilbm->colortable, and ilbm->ncolors
  1692.  *   and loading the colors into the screen's viewport
  1693.  *
  1694.  *   Note that ncolors may be more colors than you can LoadRGB4.
  1695.  *   Use MIN(ilbm->ncolors,vp->ColorMap->Count) for color count if
  1696.  *   you change the colors yourself using 1.3/2.0 functions.
  1697.  *
  1698.  * V39 - unless ilbm->IFFPFlags & IFFPF_NOCOLOR32, will do 32-bit
  1699.  *   color load under V39 and higher
  1700.  *
  1701.  * Returns 0 for success or an IFFERR (libraries/iffparse.h)
  1702.  *
  1703.  * NOTE - LoadMandPic () keeps the IFFHandle open so you can copy
  1704.  *   or examine other chunks.  You must call closeifile(iff,ilbm)
  1705.  *   to close the file and deallocate the parsed context
  1706.  *
  1707.  */
  1708.  
  1709. LONG LoadMandPic (struct ILBMInfo *ilbm,UBYTE *filename)
  1710. {
  1711. struct BitMap *TmpBM;
  1712.  
  1713. LONG error;
  1714.  
  1715.   if (! (ilbm->ParseInfo.iff)) return (CLIENT_ERROR);
  1716.  
  1717.   if (! ilbm->scr) return (CLIENT_ERROR);
  1718.  
  1719.   if (! (ilbm->vp)) ilbm->vp = &ilbm->scr->ViewPort;
  1720.  
  1721.   error = openifile (&(ilbm->ParseInfo),filename,IFFF_READ);
  1722.  
  1723.   if (! error)
  1724.   {
  1725.      error = parseifile (&(ilbm->ParseInfo),ID_FORM,ID_ILBM,ilbm->ParseInfo.propchks,ilbm->ParseInfo.collectchks,ilbm->ParseInfo.stopchks);
  1726.  
  1727.      if ((! error) || (error == IFFERR_EOC) || (error == IFFERR_EOF))
  1728.      {
  1729.         if (contextis (ilbm->ParseInfo.iff,ID_ILBM,ID_FORM))
  1730.         {
  1731.            if (GetBitMapAttr (ilbm->wrp->BitMap,BMA_FLAGS) & BMF_STANDARD)
  1732.            {
  1733.               if (! (error = loadbody (ilbm->ParseInfo.iff,ilbm->wrp->BitMap,&ilbm->Bmhd)));
  1734.            }
  1735.  
  1736.            else
  1737.            {
  1738.               if (TmpBM = AllocBitMap ((ULONG) ilbm->win->Width,(ULONG) ilbm->win->Height,(ULONG) ilbm->wrp->BitMap->Depth,BMF_INTERLEAVED | BMF_CLEAR | BMF_MINPLANES,NULL))
  1739.               {
  1740.                  if (! (error = loadbody (ilbm->ParseInfo.iff,TmpBM,&ilbm->Bmhd)))
  1741.  
  1742.                     BltBitMapRastPort (TmpBM,(LONG) ilbm->win->LeftEdge,(LONG) ilbm->win->TopEdge,ilbm->wrp,(LONG) ilbm->win->LeftEdge,(LONG) ilbm->win->TopEdge,(LONG) ilbm->win->Width,(LONG) ilbm->win->Height,0xC0);
  1743.  
  1744.                  FreeBitMap (TmpBM);
  1745.               }
  1746.            }
  1747.  
  1748.            if (! (getcolors (ilbm)))
  1749.            {
  1750.               setcolors (ilbm,ilbm->vp);
  1751.  
  1752.               freecolors (ilbm);
  1753.            }
  1754.         }
  1755.  
  1756.         else error = NOFILE;
  1757.      }
  1758.  
  1759.      closeifile (&(ilbm->ParseInfo));
  1760.   }
  1761.  
  1762.   return (error);
  1763. }
  1764.  
  1765. LONG SaveMandPic (struct ILBMInfo *ilbm,struct Chunk *chunklist1,struct Chunk *chunklist2,UBYTE *filename)
  1766. {
  1767. struct BitMap *TmpBM;
  1768.  
  1769. Color32 *colortable32;
  1770.  
  1771. UWORD count;
  1772.  
  1773. ULONG modeid;
  1774.  
  1775. LONG error = IFFERR_NOMEM;
  1776.  
  1777.   modeid = GetVPModeID (ilbm->vp);
  1778.  
  1779.   count = ilbm->vp->ColorMap->Count;
  1780.  
  1781.   if (colortable32 = (Color32 *) AllocVec ((ULONG) (sizeof (Color32) * count),MEMF_CLEAR))
  1782.   {
  1783.      if (GetBitMapAttr (ilbm->wrp->BitMap,BMA_FLAGS) & BMF_STANDARD)
  1784.      {
  1785.         GetRGB32 (ilbm->vp->ColorMap,0L,(ULONG) count,(ULONG *) colortable32);
  1786.  
  1787.         error = saveilbm (ilbm,ilbm->wrp->BitMap,modeid,ilbm->win->Width,ilbm->win->Height,ilbm->win->Width,ilbm->win->Height,colortable32,count,32,mskNone,0,chunklist1,chunklist2,filename);
  1788.      }
  1789.  
  1790.      else
  1791.      {
  1792.         if (TmpBM = AllocBitMap ((ULONG) ilbm->win->Width,(ULONG) ilbm->win->Height,(ULONG) ilbm->wrp->BitMap->Depth,BMF_INTERLEAVED | BMF_CLEAR | BMF_MINPLANES,NULL))
  1793.         {
  1794.            GetRGB32 (ilbm->vp->ColorMap,0L,(ULONG) count,(ULONG *) colortable32);
  1795.  
  1796.            BltBitMap (ilbm->wrp->BitMap,(LONG) ilbm->win->LeftEdge,(LONG) ilbm->win->TopEdge,TmpBM,(LONG) ilbm->win->LeftEdge,(LONG) ilbm->win->TopEdge,(LONG) ilbm->win->Width,(LONG) ilbm->win->Height,0xC0,0xFF,NULL);
  1797.  
  1798.            error = saveilbm (ilbm,TmpBM,modeid,ilbm->win->Width,ilbm->win->Height,ilbm->win->Width,ilbm->win->Height,colortable32,count,32,mskNone,0,chunklist1,chunklist2,filename);
  1799.  
  1800.            FreeBitMap (TmpBM);
  1801.         }
  1802.      }
  1803.  
  1804.      FreeVec (colortable32);
  1805.   }
  1806.  
  1807.   if (! error) PutDiskObject (filename,&ILBMobject);
  1808.  
  1809.   return (error);
  1810. }
  1811.  
  1812. LONG LoadPalette (struct ILBMInfo *ilbm,UBYTE *filename)
  1813. {
  1814. LONG error;
  1815.  
  1816.   error = openifile (&(ilbm->ParseInfo),filename,IFFF_READ);
  1817.  
  1818.   if (! error)
  1819.   {
  1820.      error = parseifile (&(ilbm->ParseInfo),ID_FORM,ID_ILBM,ilbm->ParseInfo.propchks,ilbm->ParseInfo.collectchks,ilbm->ParseInfo.stopchks);
  1821.  
  1822.      if ((! error) || (error == IFFERR_EOC) || (error == IFFERR_EOF))
  1823.      {
  1824.         if (! (error = getcolors (ilbm)))
  1825.         {
  1826.            setcolors (ilbm,ilbm->vp);
  1827.  
  1828.            freecolors (ilbm);
  1829.         }
  1830.      }
  1831.  
  1832.      closeifile (&(ilbm->ParseInfo));
  1833.   }
  1834.  
  1835.   return (error);
  1836. }
  1837.  
  1838. LONG SavePalette (struct ILBMInfo *ilbm,struct Chunk *chunklist,UBYTE *filename)
  1839. {
  1840. struct IFFHandle *iff;
  1841.  
  1842. struct Chunk *chunk;
  1843.  
  1844. Color32 *colortable32;
  1845.  
  1846. UWORD ncolors;
  1847.  
  1848. LONG size,error;
  1849.  
  1850. ULONG chunkID;
  1851.  
  1852.   iff = ilbm->ParseInfo.iff;
  1853.  
  1854.   ncolors = ilbm->vp->ColorMap->Count;
  1855.  
  1856.   error = openifile (&(ilbm->ParseInfo),filename,IFFF_WRITE);
  1857.  
  1858.   if (! error)
  1859.   {
  1860.     error = PushChunk (iff,ID_ILBM,ID_FORM,IFFSIZE_UNKNOWN);
  1861.  
  1862.     if (colortable32 = (Color32 *) AllocVec ((ULONG) (sizeof (Color32) * ncolors),MEMF_CLEAR))
  1863.     {
  1864.        GetRGB32 (ilbm->vp->ColorMap,0L,(ULONG) ncolors,(ULONG *) colortable32);
  1865.  
  1866.        CkErr (putcmap (iff,colortable32,ncolors,32));
  1867.  
  1868.        FreeVec (colortable32);
  1869.     }
  1870.  
  1871.     for (chunk = chunklist; chunk; chunk = chunk->ch_Next)
  1872.     {
  1873.       chunkID = chunk->ch_ID;
  1874.  
  1875.       if ((chunkID != ID_BMHD) && (chunkID != ID_CMAP) && (chunkID != ID_CAMG))
  1876.       {
  1877.         size = chunk->ch_Size == IFFSIZE_UNKNOWN ? strlen (chunk->ch_Data) : chunk->ch_Size;
  1878.  
  1879.         CkErr (PutCk (iff,chunkID,size,chunk->ch_Data));
  1880.       }
  1881.     }
  1882.  
  1883.     CkErr (PopChunk (iff));    /* close out the FORM */
  1884.  
  1885.     closeifile (&(ilbm->ParseInfo));    /* and the file */
  1886.   }
  1887.  
  1888.   return (error);
  1889. }
  1890.